﻿Imports System.Collections.Generic
Imports System.Text

Public Module MyProblem



    Public max_temperature, min_temperature, iterations As Integer

    Public Solution As New Dictionary(Of InitializeData.TVWS(), InitializeData.SecondarySystem)

    Public result As New StringBuilder

    Public j As Integer = 1

    Public RoundTimeSolution As New List(Of RoundTimeSolutionClass.Solution)

    Public removed As Boolean

    Public System_ID As New List(Of Integer)


    Public Function solve(ByVal systems As List(Of InitializeData.SecondarySystem)) As Dictionary(Of InitializeData.TVWS(), InitializeData.SecondarySystem)
        Dim Cost As New List(Of Integer)
        Dim myfunc As New backtracking(systems)
        ReadINI()
        myfunc.start(max_temperature, min_temperature, iterations)
        Dim RoundSystems As New List(Of InitializeData.SecondarySystem)
        myfunc.fragmentation = myfunc.calculateStartFragmentation
        While (j <= 10)
            System_ID.Clear()
            Remove()
            For i As Integer = 0 To systems.Count - 1
                If (systems.Item(i).start = j) Then
                    RoundSystems.Add(systems.Item(i))
                    If (systems.Item(i).name.Contains("LTE")) Then
                        backtracking.fdd = True
                    End If
                End If
            Next i
            Dim Temp_Solution As New Dictionary(Of InitializeData.TVWS(), InitializeData.SecondarySystem)
            Dim Priority_One_Systems As New List(Of InitializeData.SecondarySystem)
            Dim Priority_Two_Systems As New List(Of InitializeData.SecondarySystem)
            For Each RoundSystem As InitializeData.SecondarySystem In RoundSystems
                Select Case RoundSystem.priority
                    Case 1
                        Priority_One_Systems.Add(RoundSystem)
                    Case 2
                        Priority_Two_Systems.Add(RoundSystem)
                End Select
            Next RoundSystem
            For Each Priority_One_System As InitializeData.SecondarySystem In Priority_One_Systems
                myfunc.Initialization()
                Dim Temp_List As New List(Of InitializeData.SecondarySystem)
                Temp_List.Add(Priority_One_System)
                Dim Temporary As New Dictionary(Of InitializeData.TVWS(), InitializeData.SecondarySystem)
                For Each Entry As KeyValuePair(Of InitializeData.TVWS(), InitializeData.SecondarySystem) In myfunc.back(Temp_List)
                    Temporary.Add(Entry.Key, Entry.Value)
                Next Entry
                For Each Entry As KeyValuePair(Of InitializeData.TVWS(), InitializeData.SecondarySystem) In Temporary
                    Temp_Solution.Add(Entry.Key, Entry.Value)
                Next Entry

                If (Temporary.Count = 0) Then
                    result.Append("<b>System ").Append(Priority_One_System.name).Append(" with ID ").Append(Priority_One_System.id).Append(" cannot be inserted</b>")
                End If
                Temporary.Clear()
            Next Priority_One_System
            For Each Priority_Two_System As InitializeData.SecondarySystem In Priority_Two_Systems
                myfunc.Initialization()
                Dim Temp_List As New List(Of InitializeData.SecondarySystem)
                Temp_List.Add(Priority_Two_System)
                Dim Temporary As New Dictionary(Of InitializeData.TVWS(), InitializeData.SecondarySystem)
                For Each Entry As KeyValuePair(Of InitializeData.TVWS(), InitializeData.SecondarySystem) In myfunc.back(Temp_List)
                    Temporary.Add(Entry.Key, Entry.Value)
                Next Entry
                For Each Entry As KeyValuePair(Of InitializeData.TVWS(), InitializeData.SecondarySystem) In Temporary
                    Temp_Solution.Add(Entry.Key, Entry.Value)
                Next Entry

                If (Temporary.Count = 0) Then
                    result.Append("<b>System ").Append(Priority_Two_System.name).Append(" with ID ").Append(Priority_Two_System.id).Append(" cannot be inserted</b>")
                End If
                Temporary.Clear()
            Next Priority_Two_System

            RoundTimeSolution.Add(New RoundTimeSolutionClass.Solution(j, backtracking.return_fragmentation, backtracking.end_time - backtracking.start_time, New Dictionary(Of InitializeData.TVWS(), InitializeData.SecondarySystem)(Temp_Solution)))
            Cost.Add(backtracking.return_cost)
            For Each entry As KeyValuePair(Of InitializeData.TVWS(), InitializeData.SecondarySystem) In Temp_Solution
                Solution.Add(entry.Key, entry.Value)
            Next entry
            result.Append("<HTML><HEAD><TITLE>Spectrum Allocation Results</TITLE></HEAD><link rel='stylesheet' type='text/css' href='Results.css' /><BODY>")
            If (removed) Then
                For l As Integer = 0 To System_ID.Count - 1
                    result.Append("<p><b>System with ID ").Append(System_ID.Item(l)).Append(" removed</b></p>")
                Next l
                removed = False
            End If
            result.Append(Print(Temp_Solution))
            myfunc.Initialization()
            RoundSystems.Clear()
            backtracking.fdd = False
            j = j + 1
        End While
        result.Append("</BODY>")
        Dim b As New BarChart(Cost)

        Return Solution
    End Function


    Public Function Print(ByVal Solution As Dictionary(Of InitializeData.TVWS(), InitializeData.SecondarySystem)) As StringBuilder
        Dim Result As New StringBuilder
        Result.Append("<p>").Append("Round: ").Append(j).Append("</p>")
        If (Solution.Count = 0) Then
            Result.Append("<p>No Solution</p>")
        Else
            Result.Append("<table><tr><td>System</td><td>Channels</td></tr>")
            For Each entry As KeyValuePair(Of InitializeData.TVWS(), InitializeData.SecondarySystem) In Solution
                Result.Append("<tr><td>").Append(entry.Value().name).Append("   ").Append(entry.Value().id).Append("</td><td>")
                Dim i As Integer = 0
                For Each channel As InitializeData.TVWS In entry.Key
                    If (i = entry.Value.bandwidth) Then
                        Result.Append(",")
                        Result.Append("<font color='red'>").Append("  ").Append(channel.id).Append(" subid  ").Append(channel.subid).Append(" (Guard Interval Channel) ").Append("</font>")
                        Exit For
                    End If
                    Result.Append(",")
                    Result.Append("  ").Append(channel.id).Append(" subid  ").Append(channel.subid)
                    i = i + 1
                Next channel
            Next entry
            Result.Append("</td></tr></table>")
            Result.Append("fragmentation: ").Append("<b>").Append(Format(backtracking.return_fragmentation)).Append("</b>").Append(" ")
            Result.Append("Cost: ").Append("<b>").Append(Format(backtracking.return_cost)).Append("</b>").Append(" ")
            Result.Append("Temperature: ").Append("<b>").Append(Format(backtracking.return_temperature)).Append("</b>").Append(" ")
            Result.Append("Spectrum Utilization: ").Append("<b>").Append(Format(backtracking.Spectrum_Utilization)).Append("</b>").Append(" ")
            Result.Append("Bw exploited: ").Append("<b>").Append(Format(backtracking.bw_exploited)).Append("</b>").Append(" ")
            Result.Append("Time elapsed: ").Append("<b>").Append(backtracking.end_time - backtracking.start_time).Append("</b>").Append(" ")
        End If
        Return Result
    End Function


    Public Sub ReadINI()
        iterations = 1000
        max_temperature = 100
        min_temperature = 2
    End Sub




    Public Sub Remove()
        For Each Entry As KeyValuePair(Of InitializeData.TVWS(), InitializeData.SecondarySystem) In Solution
            Dim system As InitializeData.SecondarySystem = Entry.Value
            Dim channels As InitializeData.TVWS() = Entry.Key
            If (system.EndTime = (j - 1)) Then
                System_ID.Add(system.id)
                For Each currentChannel As InitializeData.TVWS In channels
                    backtracking.Total_channelsUsed.Remove(currentChannel)
                    For i As Integer = 0 To backtracking.tvws_local.Count - 1
                        If ((backtracking.tvws_local.Item(i).id = currentChannel.id) And (backtracking.tvws_local.Item(i).subid = currentChannel.subid)) Then
                            backtracking.tvws_local.Item(i).isAvailable = True
                        End If
                    Next i
                Next currentChannel
                removed = True
            End If
        Next Entry
        removeDuplicate(System_ID)
    End Sub

    Public Sub removeDuplicate(ByRef arlList As List(Of Integer))
        Dim h As New HashSet(Of Integer)
        For Each item As Integer In arlList
            h.Add(item)
        Next item
        arlList.Clear()
        For Each item As Integer In h
            arlList.Add(item)
        Next item
    End Sub
End Module
